﻿using GalaSoft.MvvmLight.Messaging;
using System;
using System.Linq;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Threading;

namespace Songhay.Silverlight.BiggestBox.Views
{
    using Songhay.Mvvm;
    using Songhay.Mvvm.Models;
    using Songhay.Mvvm.Views;

    /// <summary>
    /// The root visual of this application.
    /// </summary>
    public partial class ClientView : UserControl, INavigationFrame
    {
        /// <summary>
        /// Initializes a new instance
        /// of the <see cref="ClientView"/> class.
        /// </summary>
        public ClientView()
        {
            InitializeComponent();

            this.IndexFrame.ContentLoader = new BiggestBoxNavigationContentLoader();

            #region eventing:

            this.IndexFrame.Loaded += (s, args) =>
            {
                Messenger.Default.Register<LightNotificationMessageAction<INavigationFrame>>(this,
                message =>
                {
                    if(message.Source != LightMessageSource.CompositionMessagingCore) return;
                    if(message.Notification != "ClientView") return;

                    message.Execute(this);
                });
            };

            this.IndexFrame.Navigated += (s, args) =>
            {
                this._isNavigating = false;
            };

            this.IndexFrame.Navigating += (s, args) =>
            {
                if(args.Uri == null) args.Cancel = true;

                if(this._isApplicationComposed)
                {
                    this._cachedTargetUri = null;
                }
                else
                {
                    this._cachedTargetUri = new Uri("#" + args.Uri.OriginalString, UriKind.Relative);
                    args.Cancel = true;
                }

                this._isNavigating = !args.Cancel;
            };

            this.IndexFrame.NavigationFailed += (s, args) =>
            {
                args.Handled = true;
                var errorWin = new ErrorChildWindow(args.Uri);
                errorWin.Show();
            };

            #endregion

            #region messaging:

            Messenger.Default.Register<LightMessage<ChildWindow>>(this,
            message =>
            {
                if(message.Source != LightMessageSource.ViewEventClosing) return;
                if((message.UniqueId != "AlertChildWindow") &&
                    (message.UniqueId != "PackedXamlChildWindow")) return;
                this._navigationTimer.Start();
            });

            Messenger.Default.Register<LightMessage<string>>(this,
            message =>
            {
                if(message.Source != LightMessageSource.ApplicationComposed) return;
                if(message.Content != "BiggestBoxCompositionHost") return;

                this._isApplicationComposed = true;

                if(this._cachedTargetUri == null)
                    HtmlPage.Window.Navigate(new Uri("#/index", UriKind.Relative));
                else
                {
                    if(this._cachedTargetUri.OriginalString.Contains(HtmlPage.Window.CurrentBookmark))
                    {
                        var notificationAction = new LightNotificationMessageAction<Page>(HtmlPage.Window.CurrentBookmark,
                        page =>
                        {
                            this.IndexFrame.Content = page;
                            var view = page as IComposableView;
                            if(view != null) view.DoNavigateTo(new Uri(HtmlPage.Window.CurrentBookmark, UriKind.Relative));
                        })
                        {
                            Source = LightMessageSource.View,
                            UniqueId = "ClientViewApplicationComposed"
                        };
                        Messenger.Default.Send(notificationAction);
                    }
                    else
                        HtmlPage.Window.Navigate(this._cachedTargetUri, "_self");
                }
            });

            #endregion

            #region timing:

            this._navigationTimer = new DispatcherTimer();
            this._navigationTimer.Interval = TimeSpan.FromSeconds(1);
            this._navigationTimer.Tick += (s, args) =>
            {
                this._navigationTimer.Stop();

                if(!this.IndexFrame.CanGoBack)
                {
                    var x = HtmlPage.Window.CurrentBookmark.Count(i => i == '/');
                    if(x == 3) //Navigation cannot go back from a deep link to a sample.
                    {
                        var index = HtmlPage.Window.CurrentBookmark.LastIndexOf('/');
                        var bookmark = HtmlPage.Window.CurrentBookmark.Remove(index);
                        HtmlPage.Window.Navigate(new Uri("#" + bookmark, UriKind.Relative));
                    }
                    return;
                }
                this.IndexFrame.GoBack();
            };

            #endregion
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is navigating.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is navigating; otherwise, <c>false</c>.
        /// </value>
        /// <remarks>
        /// A conventional Composition Messaging design pattern would use this member
        /// to prevent blocking an asynchronous navigation operation.
        /// </remarks>
        public bool IsNavigating
        {
            get { return this._isNavigating; }
        }

        /// <summary>
        /// Gets or sets the navigation frame.
        /// </summary>
        /// <value>The navigation frame.</value>
        /// <remarks>
        /// A conventional Composition Messaging design pattern would use this member
        /// to set the <see cref="System.Windows.Controls.Frame.ContentLoader"/> property
        /// with an object implementing <see cref="System.Windows.Navigation.INavigationContentLoader"/>.
        /// </remarks>
        public Frame NavigationFrame
        {
            get { return this.IndexFrame; }
        }

        /// <summary>
        /// Full-screen click handler.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        /// <remarks>
        /// “A Silverlight-based application can enter full-screen mode only in response to a user-initiated action.
        /// This means that you can programmatically switch to full-screen mode only in a user-input event handler.
        /// If you try to set the IsFullScreen property to true in a Startup event handler, for example,
        /// the property setting is ignored. Limiting the actions that enable full-screen mode ensures
        /// that the user is always the initiator of full-screen mode behavior. This limits malicious applications
        /// from spoofing the appearance of the operating system or other programs.”
        /// [http://msdn.microsoft.com/en-us/library/cc189023%28v=vs.95%29.aspx]
        /// </remarks>
        void FullScreenClick(object sender, System.Windows.RoutedEventArgs e)
        {
            Application.Current.Host.Content.IsFullScreen = !Application.Current.Host.Content.IsFullScreen;
        }

        bool _isNavigating;
        bool _isApplicationComposed;
        Uri _cachedTargetUri;

        /// <summary>
        /// Times the Navigation of the Frame in this View
        /// </summary>
        /// <remarks>
        /// The Navigation has to be delayed to allow Silverlight
        /// to run any animations built in to its user experience
        /// for Navigation.
        /// </remarks>
        DispatcherTimer _navigationTimer;
    }
}
